﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Reflection;

namespace Calhoon.MarkupParser
{
	public class TagConverter
	{
		protected delegate bool IsSelfClosingHandler(Tag tag);
		protected delegate HierarchyNode GetHierarchyNodeHandler(Tag tag);

		private Dictionary<string, IsSelfClosingHandler> mIsSelfClosingCallbacks;
		protected Dictionary<string, IsSelfClosingHandler> IsSelfClosingCallbacks {
			get {
				return mIsSelfClosingCallbacks;
			}
		}

		private Dictionary<string, GetHierarchyNodeHandler> mGetHierarchyNodeCallbacks;
		protected Dictionary<string, GetHierarchyNodeHandler> GetHierarchyNodeCallbacks {
			get {
				return mGetHierarchyNodeCallbacks;
			}
		}

		public bool IsSelfClosing(Tag tag) {
			if (mIsSelfClosingCallbacks.ContainsKey(tag.TagName.ToUpperInvariant())) {
				return mIsSelfClosingCallbacks[tag.TagName.ToUpperInvariant()](tag);
			}
			else {
				return DefaultIsSelfClosing(tag);
			}
		}

		protected virtual bool DefaultIsSelfClosing(Tag tag) {
			return false;
		}

		public HierarchyNode GetHierarchyNode(Tag tag) {
			if (mGetHierarchyNodeCallbacks.ContainsKey(tag.TagName.ToUpperInvariant())) {
				return mGetHierarchyNodeCallbacks[tag.TagName.ToUpperInvariant()](tag);
			}
			else {
				return DefaultGetHierarchyNode(tag);
			}
		}

		protected virtual HierarchyNode DefaultGetHierarchyNode(Tag tag) {
			return new HierarchyNode(tag);
		}

		public TagConverter() {
			LoadCallbackDictionaries();
		}

		protected void LoadCallbackDictionaries() {
			MethodInfo[] methods = this.GetType().GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);

			mIsSelfClosingCallbacks = new Dictionary<string, IsSelfClosingHandler>();
			foreach (System.Reflection.MethodInfo method in methods) {
				object[] attributes = method.GetCustomAttributes(typeof(IsSelfClosingMethodAttribute), true);
				foreach (IsSelfClosingMethodAttribute attribute in attributes) {
					mIsSelfClosingCallbacks.Add(attribute.TagName.ToUpperInvariant(), (IsSelfClosingHandler)Delegate.CreateDelegate(typeof(IsSelfClosingHandler), this, method));
				}
			}


			mGetHierarchyNodeCallbacks = new Dictionary<string, GetHierarchyNodeHandler>();
			foreach (System.Reflection.MethodInfo method in methods) {
				object[] attributes = method.GetCustomAttributes(typeof(GetHierarchyNodeMethodAttribute), true);
				foreach (GetHierarchyNodeMethodAttribute attribute in attributes) {
					mGetHierarchyNodeCallbacks.Add(attribute.TagName.ToUpperInvariant(), (GetHierarchyNodeHandler)Delegate.CreateDelegate(typeof(GetHierarchyNodeHandler), this, method));
				}
			}
		}

		[IsSelfClosingMethod("_Literal")]
		protected virtual bool LiteralIsSelfClosing(Tag tag) {
			return true;
		}

		[GetHierarchyNodeMethod("_Literal")]
		protected virtual HierarchyNode LiteralGetHierarchyNode(Tag tag) {
			return new LiteralNode(tag);
		}

		[IsSelfClosingMethod("_Comment")]
		protected virtual bool CommentIsSelfClosing(Tag tag) {
			return true;
		}

		[GetHierarchyNodeMethod("_Comment")]
		protected virtual HierarchyNode CommentGetHierarchyNode(Tag tag) {
			return new CommentNode(tag);
		}
	}
}